package puzzle.devtools;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.io.File;
import java.net.URL;
import java.text.MessageFormat;
import java.util.prefs.Preferences;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileSystemView;
import org.newdawn.slick.util.Log;
import puzzle.devtools.AbstractEditor;
import puzzle.util.ResourceManager;

public abstract class AbstractEditor extends JFrame {

  public static void loadUI() {
    //Attempts to set a fancy L&F
    try {
      //the default LAF to revert to
      String laf = ResourceManager.getString("devtools.defaultLAF", 
                            "org.jvnet.substance.skin.SubstanceModerateLookAndFeel");
      UIManager.setLookAndFeel(laf);
    }
    //user doesn't have that L&F installed
    catch (Exception e) {
      Log.warn("Publisher LAF not found.");
      //use regular system L&F
      try {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
        Log.info("Setting system LAF.");
      } catch (Exception e2) {
        Log.error(e2);
      }
    }
    JFrame.setDefaultLookAndFeelDecorated(true);
    JDialog.setDefaultLookAndFeelDecorated(true);
  }
   
  private JFileChooser jfc = null;
  private JMenuBar menuBar = null;
  private JPanel aboutPane = null;
  
  
  public abstract Preferences getPrefs();
  public abstract String getEditorName();
  public abstract String getPrefix();
  
  public AbstractEditor() {
    super();
    init();
  }
  
  public AbstractEditor(String s) {
    super(s);
    init();
  }
  
  protected void init() {
    String ref = ResourceManager.getString("icon.window", "data/icon.gif");
    URL u = ResourceManager.getResource(ref);
    setIconImage(new ImageIcon(u).getImage());
    
    Runtime.getRuntime().addShutdownHook(new Thread() {
      
      {
        setName(AbstractEditor.this.getName()+" Pref Setter");
      }
        
      public void run() {
        cleanup();
      }
    });
  }
  
  
  public JFileChooser getJFileChooser() {
    if (jfc==null) {
      //gets the last known jfilechooser directory
      String dir = getPrefs().get("jfilechooser.dir", null);
      
      //if it doesn't exist, use default directory
      if (dir==null||dir.length()==0) {
        File f = FileSystemView.getFileSystemView().getDefaultDirectory();
        dir = f.getAbsolutePath();
      }
      return (jfc=new JFileChooser(dir));
    }
    else 
      return jfc;
  }
  
  public File getFile(String command) {
    return getFile(this, command);
  }
  
  public File getFile(Component parent, String command) {
    if (getJFileChooser().showDialog(parent, command) 
               != JFileChooser.APPROVE_OPTION) {
      return null;           
    }
     
    File f = getJFileChooser().getSelectedFile();
    getJFileChooser().setSelectedFile(null);
    return f;
  }
  
  /** The first character of ext doesn't need to be a period. */
  public File toExtension(File f, String ext) {
    if (f==null||ext==null)
      return f;
    
    if (ext.length()==0) {
      String n = f.getName();
      int i;
      if ( (i=n.indexOf('.')) != -1) {
        n = n.substring(0, i);
      }
      return new File(n);
    }
    
    if (ext.charAt(0)!='.')
      ext = "."+ext;
    
    String name = f.getName();
    
    //if the file doesn't need changing
    if (name==null||name.length()==0
            || name.toUpperCase().endsWith(ext.toUpperCase())) {
      return f;
    }
    
    //gets the new file
    return new File(f.getPath()+ext);
  }
  
  protected void cleanup() {
    if (jfc!=null) {
      String dir = jfc.getCurrentDirectory().getAbsolutePath();
      getPrefs().put("jfilechooser.dir", dir);
    }
  }
  
  public JMenuBar getJMenuBar() {
    return (menuBar!=null) ? menuBar : (menuBar=new JMenuBar());
  }
  
  public void setJMenuBar(JMenuBar bar) {
    this.menuBar = bar;
    super.setJMenuBar(bar);
  }
  
  public void showAboutDialog() {
    if (aboutPane==null) {
      String ref = ResourceManager.getString("icon.about", "data/logo-small.gif");
      JLabel logo = new JLabel();
      
      try { logo.setIcon(new ImageIcon(ResourceManager.getResource(ref))); }
      catch (Exception e) { 
        Log.warn("Can't find small logo");
        logo.setText("Icon not found"); 
      }
      
      String about = ResourceManager.getString(getPrefix()+".about", "ball puzzle Java game");
      about = MessageFormat.format(about, ResourceManager.getString("author", "undisclosed"));
      JLabel text = new JLabel(about);
      
      logo.setBorder(BorderFactory.createLineBorder(java.awt.Color.black));
      
      JPanel logoPane = new JPanel();
      logoPane.add(logo);
      
      JPanel textPane = new JPanel();
      textPane.add(text);
      
      aboutPane = new JPanel(new BorderLayout());
      aboutPane.add(logoPane, BorderLayout.NORTH);
      aboutPane.add(textPane, BorderLayout.SOUTH);
    }
    String abtitle = ResourceManager.getString("ui.menu.about", "About");
    JOptionPane.showMessageDialog(this, aboutPane, abtitle, JOptionPane.PLAIN_MESSAGE);
  }
  
  public JMenuItem newJMenuItem(String name, ActionListener l) {
    final JMenuItem jmi = new JMenuItem(name);
    jmi.addActionListener(l);
    return jmi;
  }
  
  public JMenuItem newQuitMenuItem() {
    String str = ResourceManager.getString("ui.menu.quit", "Quit");
    JMenuItem i = newJMenuItem(str, new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        System.exit(0);
      }
    });
    i.setAccelerator(KeyStroke.getKeyStroke(
                            KeyEvent.VK_Q, InputEvent.CTRL_MASK));
    return i;
  }
  
  public JMenuItem newAboutMenuItem() {
    String str = ResourceManager.getString("ui.menu.about", "About");
    JMenuItem i = newJMenuItem(str, new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        showAboutDialog();
      }
    });
    return i;
  }
  
  
  public class BPuzFileFilter extends javax.swing.filechooser.FileFilter {
    
    public boolean accept(File f) {
      if (f!=null) {
        if (f.isDirectory())
          return true;
        return f.getName().toLowerCase().endsWith(".bpuz");
      }
      else 
        return false;
    }
    
    public String getDescription() {
      return "BPuz Data (.bpuz)";
    }
  }
  
  public class XMLFileFilter extends javax.swing.filechooser.FileFilter {
    
    public boolean accept(File f) {
      if (f!=null) {
        if (f.isDirectory())
          return true;
        return f.getName().toLowerCase().endsWith(".xml");
      }
      else 
        return false;
    }
    
    public String getDescription() {
      return "XML File (.xml)";
    }
  }
}